home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / sox / rate.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  4KB  |  165 lines

  1.  
  2. /*
  3.  * July 5, 1991
  4.  * Copyright 1991 Lance Norskog And Sundry Contributors
  5.  * This source code is freely redistributable and may be used for
  6.  * any purpose.  This copyright notice must be maintained. 
  7.  * Lance Norskog And Sundry Contributors are not responsible for 
  8.  * the consequences of using this software.
  9.  */
  10.  
  11. /*
  12.  * Sound Tools rate change effect file.
  13.  */
  14.  
  15. #include <math.h>
  16. #include "st.h"
  17.  
  18. /*
  19.  * Least Common Multiple Linear Interpolation 
  20.  *
  21.  * Find least common multiple of the two sample rates.
  22.  * Construct the signal at the LCM by interpolating successive
  23.  * input samples as straight lines.  Pull output samples from
  24.  * this line at output rate.
  25.  *
  26.  * Of course, actually calculate only the output samples.
  27.  *
  28.  * LCM must be 32 bits or less.  Two prime number sample rates
  29.  * between 32768 and 65535 will yield a 32-bit LCM, so this is 
  30.  * stretching it.
  31.  */
  32.  
  33. /*
  34.  * Algorithm:
  35.  *  
  36.  *  Generate a master sample clock from the LCM of the two rates.
  37.  *  Interpolate linearly along it.  Count up input and output skips.
  38.  *
  39.  *  Input:   |inskip |       |       |       |       |
  40.  *                                                                      
  41.  *                                                                      
  42.  *                                                                      
  43.  *  LCM:     |   |   |   |   |   |   |   |   |   |   |
  44.  *                                                                      
  45.  *                                                                      
  46.  *                                                                      
  47.  *  Output:  |  outskip  |           |           | 
  48.  *
  49.  *                                                                      
  50.  */
  51.  
  52.  
  53. /* Private data for Lerp via LCM file */
  54. typedef struct ratestuff {
  55.     u_l    lcmrate;        /* least common multiple of rates */
  56.     u_l    inskip, outskip;    /* LCM increments for I & O rates */
  57.     u_l    total;
  58.     u_l    intot, outtot;        /* total samples in terms of LCM rate */
  59.     long    lastsamp;
  60. } *rate_t;
  61.  
  62. /*
  63.  * Process options
  64.  */
  65. rate_getopts(effp, n, argv) 
  66. eff_t effp;
  67. int n;
  68. char **argv;
  69. {
  70.     if (n)
  71.         fail("Rate effect takes no options.");
  72. }
  73.  
  74. /*
  75.  * Prepare processing.
  76.  */
  77. rate_start(effp)
  78. eff_t effp;
  79. {
  80.     rate_t rate = (rate_t) effp->priv;
  81.     IMPORT long lcm();
  82.     
  83.     rate->lcmrate = lcm((long)effp->ininfo.rate, (long)effp->outinfo.rate);
  84.     /* Cursory check for LCM overflow.  
  85.      * If both rate are below 65k, there should be no problem.
  86.      * 16 bits x 16 bits = 32 bits, which we can handle.
  87.      */
  88.     rate->inskip = rate->lcmrate / effp->ininfo.rate;
  89.     rate->outskip = rate->lcmrate / effp->outinfo.rate; 
  90.     rate->total = rate->intot = rate->outtot = 0;
  91.     rate->lastsamp = 0;
  92. }
  93.  
  94. /*
  95.  * Processed signed long samples from ibuf to obuf.
  96.  * Return number of samples processed.
  97.  */
  98.  
  99. rate_flow(effp, ibuf, obuf, isamp, osamp)
  100. eff_t effp;
  101. long *ibuf, *obuf;
  102. int *isamp, *osamp;
  103. {
  104.     rate_t rate = (rate_t) effp->priv;
  105.     int len, done;
  106.     long *istart = ibuf;
  107.     long last;
  108.  
  109.     done = 0;
  110.     if (rate->total == 0) {
  111.         /* Emit first sample.  We know the fence posts meet. */
  112.         *obuf = *ibuf++;
  113.         /* Count up until have right input samples */
  114.             rate->lastsamp = *obuf++ >> 16;
  115.         done = 1;
  116.         rate->total = 1;
  117.         /* advance to second output */
  118.         rate->outtot += rate->outskip;
  119.         /* advance input range to span next output */
  120.         while ((rate->intot + rate->inskip) <= rate->outtot){
  121.             last = *ibuf++ / 65536;
  122.             rate->intot += rate->inskip;
  123.         }
  124.     }
  125.     /* number of output samples the input can feed */
  126.     len = (*isamp * rate->inskip) / rate->outskip;
  127.     if (len > *osamp)
  128.         len = *osamp;
  129.     last = rate->lastsamp;
  130.     for(; done < len; done++) {
  131.         *obuf = last;
  132.         *obuf += ((float)((*ibuf / 65536)  - last)* ((float)rate->outtot - 
  133.                 rate->intot))/rate->inskip;
  134.         *obuf *= 65536;
  135.         obuf++;
  136.         /* advance to next output */
  137.         rate->outtot += rate->outskip;
  138.         /* advance input range to span next output */
  139.         while ((rate->intot + rate->inskip) <= rate->outtot){
  140.             last = *ibuf++ >> 16;
  141.             rate->intot += rate->inskip;
  142.             if (ibuf - istart == *isamp)
  143.                 goto out;
  144.         }
  145.         /* long samples with high LCM's overrun counters! */
  146.         if (rate->outtot == rate->intot)
  147.             rate->outtot = rate->intot = 0;
  148.     }
  149. out:
  150.     *isamp = ibuf - istart;
  151.     *osamp = len;
  152.     rate->lastsamp = last;
  153. }
  154.  
  155. /*
  156.  * Do anything required when you stop reading samples.  
  157.  * Don't close input file! 
  158.  */
  159. rate_stop(effp)
  160. eff_t effp;
  161. {
  162.     /* nothing to do */
  163. }
  164.  
  165.